package cbr.resilienceManager.qmul.gemom;

import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Label;
import java.awt.TextArea;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import javax.swing.JFrame;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.JSplitPane;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.ListSelectionModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;
import javax.swing.text.DefaultCaret;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
import javax.swing.JCheckBox;

import com.qsphere.boundary.gemom.GEMOMBrokerAdapter;
import com.qsphere.boundary.gemom.GEMOMClientData;
import com.qsphere.boundary.gemom.GEMOMData;
import com.qsphere.boundary.gemom.GEMOMListener;
import com.qsphere.boundary.gemom.GEMOMMessageType;
import com.qsphere.boundary.gemom.GEMOMParameters;
import com.qsphere.boundary.gemom.impl.GEMOMBrokerAdapterImpl;
import com.qsphere.boundary.gemom.GEMOMHints;

import inl.resilienceManager.qmul.gemom.iniFrame;

import ac.uk.qmul.gemom.scenario.DemoResource;
import ac.uk.qmul.gemom.scenario.Subscription;
import ac.uk.qmul.gemom.scenario.Util;
 

/**
 * 
 * CBR Resilience Service client using GEMOM publish/subscribe interfaces
 * 
 * COPYRIGHT DISCLAIMER
 * Synopsis: All the source codes presented in this document are intellectual
 * properties of Queen Mary, University of London.
 * 
 * @year 2010
 * @author Peng Jiang, John Bigham, Jiayi Wu Jinfu Wang------------QMUL
 * @version 1.0 
 */
public class CbrServiceClient extends JPanel implements ActionListener, GEMOMListener, ItemListener{

	private static final String PUBLISH = "publish";
	private static final String SUBSCRIBE = "subscribe";
	private static final String RENAME = "rename";
	private static final String DELETE = "delete";
	private static final String MOVE_TOPIC = "moveTopic";
	private static final String NAMESPACE_SUBSCRIBE = "namespaceSubscribe";
	private static final String NAMESPACE_RENAME = "namespaceRename";
	private static final String NAMESPACE_MOVE = "namespaceMove";
	private static final String NAMESPACE_DELETE = "namespaceDelete";
	private static final String CONNECT = "connect";
	private static final String DISCONNECT = "disconnect";
	private static final String AUTO_SUBSCRIBE = "autoSubscribe";
	
	private static final String OPTION_SUBSCRIBE = "optionSubscribe";
	private static final String OPTION_UNSUBSCRIBE = "optionUnsubscribe";
	  
	private static final String SERVICE_ON = "start counter";
	private static final String SERVICE_OFF = "stop counter";
	  
	
	private int id; 

	private static final int NAMESPACE_LABEL_WIDTH = 140;
	private static final int NAMESPACE_FIELD_X = NAMESPACE_LABEL_WIDTH + 15;
	private static final int SECOND_COLUMN_FIELD_WIDTH = 125;
	private static final int SECOND_COLUMN_LABEL_X = 220;
	private static final int SECOND_COLUMN_LABEL_WIDTH = 120;
	private static final int SECOND_COLUMN_FIELD_X = SECOND_COLUMN_LABEL_X
			+ SECOND_COLUMN_LABEL_WIDTH;

	private static final int TITLE_HEIGHT = 25;

	protected static final String VOLUMETRY_TEST_TOPIC = "__FAST1";
	protected boolean m_showVolumetryMonitorMessages = true;
	protected int m_updateCounter = 0;
	protected int m_volumetryTestPublishCount = 100;

	protected GEMOMBrokerAdapter m_broker = null;

	// Demo GUI controls
	protected TextField[] m_fieldNameFields = new TextField[4];
	protected TextField[] m_fieldValueFields = new TextField[4];
	protected TextField m_topicField = new TextField();
	protected TextField m_namespaceField = new TextField();
	protected TextField m_subscribeTopicField = new TextField();
	protected TextField m_namespaceSubscribeTopicField = new TextField();

	protected TextField m_renameTopicField = new TextField();
	protected TextField m_namespaceRenameTopicField = new TextField();
	protected TextField m_newTopicField = new TextField();
	// protected TextField m_namespaceNewTopicField = new TextField();

	protected TextField m_deleteTopicField = new TextField();
	protected TextField m_namespaceDeleteTopicField = new TextField();

	protected TextField m_namespaceSubscribeField = new TextField();
	protected TextField m_namespaceRenameField = new TextField();
	protected TextField m_namespaceNewField = new TextField();
	protected TextField m_namespaceDeleteField = new TextField();

	protected TextField m_moveTopicField = new TextField();
	protected TextField m_sourceNamespaceMoveTopicField = new TextField();
	protected TextField m_destinationNamespaceMoveTopicField = new TextField();

	protected TextField m_namespaceMoveField = new TextField();
	protected TextField m_namespaceMoveDestinationField = new TextField();
	
	protected TextField m_weightField = new TextField();

	protected JTextArea m_monitorAllSubArea = new JTextArea();
	protected JTextArea m_monitorSubArea = new JTextArea();
	protected JTextArea m_monitorMainArea = new JTextArea();
	
	// the JTable used to replace the text area
	protected JTable AllSubTable;
	protected JTable SubTable;
	
	// setup the table for the 
	protected String[] colName={"Namespace","Topic","Field Name","Field Value"};
	
	protected DateFormat m_sdf = SimpleDateFormat
			.getTimeInstance(SimpleDateFormat.MEDIUM);
	
	private Button connectButton;
	private Button disconnectButton;
	private Button autosubButton;
	private Button subscribeButton;
	private Button unsubscribeButton;
	
	private Button cbrOnButton;
	private Button cbrOffButton;
	
	private JCheckBox autoResponseOnBox;
  
	private boolean m_isConnected = false; 
	
	private boolean isInitialised = false;

	private JTree tree;
	
    protected JSplitPane splitPane, mainSplitPane;
    
    protected JScrollPane scrollMainMonitor = new JScrollPane();
    protected JScrollPane scrollNsMonitor = new JScrollPane();
    protected JScrollPane scrollNsTree = new JScrollPane();
    protected JScrollPane scrollSubMonitor = new JScrollPane();
    
	protected TextField ipstring= new TextField();
	protected TextField portstring= new TextField();
	
	protected TextField namespaceField= new TextField();
	protected TextField topicField= new TextField();
 	  
	private Subscription subscription;
	 
	private String[] updateStrings = {"", ""}; 
	 
	// Code Map:   0 - Update All Namespace & Topics; 1 - Update Selected Namespace; 2 - Update Selected Topic
	private int updateCode = -1;
	
	private boolean m_publishToSystemOut = false;
	
	private GEMOMParameters connectParameters;

	private String client_ip;
	
	private String client_port;
	    
	private int tableRowCount = 30;
	
	private boolean shouldAutoRespond = false;
	
	private boolean cbrResilienceStarted = false;
	
	private CbrOnUpdate cbrService;
	
	// private String m_psProxyIP;

	public CbrServiceClient() {
		   
		//setTitle("AutoSubscriber " + id);
		//setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		//initialiseStartupParameters();

		JPanel panel = new JPanel();
		
		panel.setLayout(new BorderLayout());
		
		this.setBounds(10, 10, 1000, 600);
		this.setLayout(new GridLayout(1, 2));
		
		panel.setBounds(10, 10, 600, 600);

		DefaultMutableTreeNode top = new DefaultMutableTreeNode("All namespaces");
		tree = new JTree(top);

	    tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);

		tree.addMouseListener(new MouseAdapter() {
			public void mousePressed(MouseEvent event) {
				if (((event.getModifiers() & InputEvent.BUTTON3_MASK) != 0)
						&& (tree.getSelectionCount() > 0)) {
					//showMenu(event.getX(), event.getY());
				}
			}
		});
		
		tree.addTreeSelectionListener(new TreeSelectionListener () {
			public void valueChanged(TreeSelectionEvent e) {
				//TreePath path = e.getPath();
				//String text = path.getPathComponent(path.getPathCount() - 1).toString();
				//String text=Datasaver.pathtransfer(path.toString());
				//textField.setText(text);
				
			    DefaultMutableTreeNode node = (DefaultMutableTreeNode)tree.getLastSelectedPathComponent();

			    String rootName = tree.getModel().getRoot().toString();
			    
                if (node == null){
                //Nothing is selected.
                    setUpdateSetting(false, null, null);
                    return;
                }

                Object nodeInfo = node.getUserObject();
                // topic or namespace selected
                
                //printLineInSubMonitor("selected node = " + (String)nodeInfo);
                //printLineInSubMonitor("parent node = " + node.getParent().toString());
                
                if(!node.isRoot()){
                    if (node.isLeaf()){
                	    // topic is selected
                	    if (!node.getParent().toString().equalsIgnoreCase(rootName)){
                            String topicName = (String)nodeInfo;
                            setUpdateSetting(false, node.getParent().toString(), topicName);
                	    }
                	     //A particular namespace selected
                	    else{
                    	    String nsName = (String)nodeInfo;
                    	    setUpdateSetting(false, nsName, "");
                	    }
                	    return;
                    }
                }
                //All namespace selected
                else{
                	setUpdateSetting(true, "", "");
                }
               
			}
		});
		
		//textField.setEditable(false);
		scrollMainMonitor.getViewport().add(m_monitorMainArea);

		// always update the text field view point
		DefaultCaret caret = (DefaultCaret)m_monitorMainArea.getCaret();
		caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);

		scrollMainMonitor.setPreferredSize(new Dimension(500, 100));

        scrollNsTree.getViewport().add(tree);
		
		splitPane= new JSplitPane(JSplitPane.VERTICAL_SPLIT, scrollMainMonitor, scrollNsTree);
		splitPane.setOneTouchExpandable(true);
		splitPane.setDividerLocation(150);
		
		//getContentPane().setLayout(new FlowLayout());
		
		panel.add(splitPane, "Center");
		
		// set up the connection panel
		JPanel conPanel= new JPanel(new GridLayout(4, 3));

		Label l1 = new Label("IP Address", Label.CENTER);
		Label l2= new Label("Port", Label.CENTER);

		conPanel.add(l1);
		conPanel.add(ipstring);

		conPanel.add(l2);
		conPanel.add(portstring);

		connectButton = new Button("Connect");
		connectButton.setActionCommand(CONNECT);
		connectButton.addActionListener(this);
		conPanel.add(connectButton);

		disconnectButton = new Button("Disconnect");
		disconnectButton.setActionCommand(DISCONNECT);	
		disconnectButton.addActionListener(this);
		conPanel.add(disconnectButton);
		
		/*
		autosubButton = new Button("Auto Subscribe");
		autosubButton.setActionCommand(AUTO_SUBSCRIBE);	
		autosubButton.addActionListener(this);
		conPanel.add(autosubButton);
		*/
		  
		panel.add(conPanel,"North");

		// set up the subscriber panel
		JPanel sPanel= new JPanel(new GridLayout(3, 3));

		Label l3 = new Label("Namespace", Label.CENTER);
		Label l4= new Label("Topic", Label.CENTER);

		sPanel.add(l3);
		sPanel.add(namespaceField);

		sPanel.add(l4);
		sPanel.add(topicField);
		
		subscribeButton= new Button("Subscribe");
		subscribeButton.setActionCommand(OPTION_SUBSCRIBE);
		subscribeButton.addActionListener(this);
		sPanel.add(subscribeButton);

		unsubscribeButton= new Button("Unsubscribe");
		unsubscribeButton.setActionCommand(OPTION_UNSUBSCRIBE);
		unsubscribeButton.addActionListener(this);
		sPanel.add(unsubscribeButton);

		panel.add(sPanel,"South");

		// setup the connection Tabpanel
		JPanel TabPanel = new JPanel( new GridBagLayout() );
		JLabel GTableTitle = new JLabel(  "Gbroker IP"  );
		JLabel STableTitle = new JLabel(  "Connect state" );
		
		JPanel panel2 = new JPanel();
		panel2 = new JPanel(new BorderLayout());
		panel2.setBounds(610, 10, 380, 600);
		
		DefaultTableModel model1= new DefaultTableModel(colName,tableRowCount);
		
		AllSubTable = new JTable(model1);
		scrollNsMonitor.getViewport().add(AllSubTable);
		
		DefaultTableModel model2= new DefaultTableModel(colName,tableRowCount);
		
		SubTable = new JTable(model2);
		scrollSubMonitor.getViewport().add(SubTable);
		//scrollNsMonitor.getViewport().add(m_monitorAllSubArea);
		
		//scrollSubMonitor.getViewport().add(m_monitorSubArea);

		
		mainSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, scrollNsMonitor, scrollSubMonitor);
		mainSplitPane.setOneTouchExpandable(true);
		mainSplitPane.setDividerLocation(220);
		
		//panel.add(mainSplitPane, "East");
		//mainSplitPane.setBounds(width, 0, width, height);
		//getContentPane().add(mainSplitPane);
		panel2.add(mainSplitPane, "Center");
		
        JPanel cbrPanel= new JPanel(new GridLayout(2, 2));
		
   
		//In initialization code:
	    cbrOnButton = new Button("Start CBR Resilience Service");
	    cbrOnButton.setActionCommand(SERVICE_ON);	
	    cbrOnButton.addActionListener(this);
	    cbrPanel.add(cbrOnButton);
	    
	    cbrOffButton = new Button("Stop CBR Resilience Service");
	    cbrOffButton.setActionCommand(SERVICE_OFF);	
	    cbrOffButton.addActionListener(this);
	    cbrPanel.add(cbrOffButton);
	    
	    cbrOnButton.setEnabled(true);
	    cbrOffButton.setEnabled(false);
	    
	    Label l9 = new Label("Query & Solution Monitors", Label.CENTER); 

	    Label l10 = new Label("(Upper = all, Lower = selected)", Label.CENTER); 

	    cbrPanel.add(l9); 
	    cbrPanel.add(l10); 
	    
		panel2.add(cbrPanel,"North");
		

        JPanel optionPanel= new JPanel(new GridLayout(2, 2));
		
		//In initialization code:
        autoResponseOnBox = new JCheckBox("Automatically respond to Resilience Solution Request");
        autoResponseOnBox.setMnemonic(KeyEvent.VK_O); 
        autoResponseOnBox.setSelected(false);

	    //Register a listener for the check boxes.
        autoResponseOnBox.addItemListener(this);
	    
		optionPanel.add(autoResponseOnBox);
		   
		
		panel2.add(optionPanel,"South");
		
		this.add(panel);
		this.add(panel2);
		//getContentPane().add(panel);
		
		//getContentPane().add(panel2);	

		initialiseStartupParameters();
		
		this.setVisible(true);
		
		validate();
		
		//printLineInMonitor(getTimeAsString() + ": Controls ready");
		
		//connect();
		
		
	}
 
	protected boolean checkIfInitialised(){
	    return isInitialised;
	}
	
	public void reset(){
		this.setEnabled(false);
		this.isInitialised = false;
	}
	
	private void initialiseStartupParameters() {
		// initialize startup parameters
		// m_psProxyIP = getStartupParameter("PSProxyAddress");
		// setUserName(getStartupParameter("Username"));
		// try {
		// m_showVolumetryMonitorMessages = Boolean
		// .parseBoolean(getStartupParameter("VolumetryTestShowMonitorMessages"));
		// } catch (Exception e) {
		// }
		// try {
		// m_volumetryTestPublishCount = Integer
		// .parseInt(getStartupParameter("VolumetryTestIterationCount"));
		// } catch (Exception e) {
		// }
		
		if(!checkIfInitialised()){ 
			this.subscription = new Subscription("CBR Resilience Subscription");
			
			isInitialised = true;
			  
		}
	}

	public void actionPerformed(ActionEvent actionEvent) {
		String command = actionEvent.getActionCommand();
		debug("Action command: " + command + " isNamespace subscribe: "
				+ NAMESPACE_SUBSCRIBE.equals(command));
		if (PUBLISH.equalsIgnoreCase(command)) {
			checkIfConnected();
			onPublish();
		} else if (SUBSCRIBE.equalsIgnoreCase(command)) {
			checkIfConnected();
			onSubscribe();
		} else if (RENAME.equalsIgnoreCase(command)) {
			checkIfConnected();
			onRename();
		} else if (MOVE_TOPIC.equalsIgnoreCase(command)) {
			checkIfConnected();
			onMoveTopic();
		} else if (DELETE.equalsIgnoreCase(command)) {
			checkIfConnected();
			onDelete();
		} else if (NAMESPACE_SUBSCRIBE.equalsIgnoreCase(command)) {
			checkIfConnected();
			onNamespaceSubscribe();
		} else if (NAMESPACE_RENAME.equalsIgnoreCase(command)) {
			checkIfConnected();
			onNamespaceRename();
		} else if (NAMESPACE_MOVE.equalsIgnoreCase(command)) {
			checkIfConnected();
			onNamespaceMove();
		} else if (NAMESPACE_DELETE.equalsIgnoreCase(command)) {
			checkIfConnected();
			onNamespaceDelete();
		} else if (CONNECT.equalsIgnoreCase(command)) {
			//if(checkIfAddressGiven())
			//    onConnect(ipstring.getText(), portstring.getText());
		    connect();
		} else if (DISCONNECT.equalsIgnoreCase(command)) {
			onDisconnect();
		} else if (SERVICE_ON.equalsIgnoreCase(command)) { 
			if(checkIfConnected()){ 
			    onStartCbrResilience();
			}
		} else if (SERVICE_OFF.equalsIgnoreCase(command)) {
			onStopCbrResilience();
		}  
		else if (OPTION_SUBSCRIBE.equalsIgnoreCase(command)) {
			checkIfConnected();
			onOptionSubscribe();
		} else if (OPTION_UNSUBSCRIBE.equalsIgnoreCase(command)) {
			checkIfConnected();
			onOptionUnsubscribe();
		}
		 	
		
	}
	   
	public void itemStateChanged(ItemEvent e) {
	    Object source = e.getItemSelectable();

	    if (source == autoResponseOnBox) {
	        onSwitchResponseMode(true); 
	        
	        if (e.getStateChange() == ItemEvent.DESELECTED)
		    	onSwitchResponseMode(false);
	    } 
	 
 
	}
	
	// switch the running mode of the CBR response client between automatic and maunal mode
	protected void onSwitchResponseMode(boolean should){  
		    this.shouldAutoRespond = should; 
	}
	
	public boolean checkIfConnected() {
		if (!m_isConnected) {
			boolean shouldConnect = JOptionPane
					.showConfirmDialog(
							this,
							"You're not connected to GEMOM. Do you want to connect first?",
							"Not Connected", JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION;
			
			if(shouldConnect){
			    connect();
			}
			
			/*
			if (shouldConnect && checkIfAddressGiven()) {
				onConnect(ipstring.getText(), portstring.getText());
				//connect();
			}
			*/
		}
		
		return m_isConnected;
	}

	
	private boolean checkIfAddressGiven() {
		String ip = ipstring.getText();
		String port = portstring.getText();
		
		if (ip != null && !ip.equalsIgnoreCase("") &&
			port != null && !port.equalsIgnoreCase("") ) {
			
	      return true;
		}
		else{
			 JOptionPane.showMessageDialog(this,
		               "Source broker address and port not specififed", "Error Message",
		               JOptionPane.INFORMATION_MESSAGE);
			return false;
		}
	}
	
	private void onConnect(String ip, String port) {
		
		this.client_ip = ip;
		
		this.client_port = port;
		
		this.setConnectionParameters(ip, port);

		if (getGEMOMBrokerInterface().connect(getGEMOMClientName(), null,
				connectParameters, null, null)) {
			setIsConnected(true);
		} else {
			JOptionPane.showMessageDialog(this, "Can't connect", "Error",
					JOptionPane.ERROR_MESSAGE);
		}
	}
	
	private void connect() {
		GEMOMParameters parameters = new GEMOMParameters();
	
		if (getGEMOMBrokerInterface().connect(getGEMOMClientName(), this,
				parameters, null, null)) {
			setIsConnected(true);
		} else {
			JOptionPane.showMessageDialog(this, "Can't connect", "Error",
					JOptionPane.ERROR_MESSAGE);
		}
	}

	private void onDisconnect() {
		if (getGEMOMBrokerInterface().disconnect(this, null, null)) {
			setIsConnected(false);
		} else {
			JOptionPane.showMessageDialog(this, "Can't disconnect", "Error",
					JOptionPane.ERROR_MESSAGE);
		}
		 
	}

	private void setIsConnected(boolean isConnected) {
		m_isConnected = isConnected;
		connectButton.setEnabled(!isConnected);
		disconnectButton.setEnabled(isConnected);
		if (isConnected)
			printLineInMonitor(getTimeAsString() + ": Connected");
		else
			printLineInMonitor(getTimeAsString() + ": Disconnected");
	}
	
	public void setPublishToSystemOut(boolean systemOut) {
		this.m_publishToSystemOut = systemOut;
	}
	
	// start the cbr service by firstly subscribing on the CBR query namespace. The 
	// iniSubscription() will do the work, and 
	@SuppressWarnings("deprecation")
	public void onStartCbrResilience(){ 
		
		if(checkIfConnected()){

			if(!cbrResilienceStarted){
				

				printLineInMonitor(getTimeAsString() + ": Initializing Resilience Service by subscribing to solution" +
						" queries");
				
				cbrService = new CbrOnUpdate();
				cbrResilienceStarted = true; 
				

				// makes sure the subscription happens after CbrService has
				// been initialised,or else when the queries come there will
				// be no available CbrOnUpdate obejct to process it
				initSubscription();
				
				
				cbrOnButton.setEnabled(false);
				cbrOffButton.setEnabled(true);
				
				printLineInMonitor(getTimeAsString() + ": Resilience Service initialized");
			} 
		}
	}
	
	private void onStopCbrResilience(){
		  
		//onUnSubscribe(scenarioFile.counter_namespace,client_ip+":"+client_port);
	    onNamespaceUnSubscribe(CbrUtil.CBR_QUERY_NAMESPACE);
	    onNamespaceUnSubscribe(CbrUtil.CBR_SOLUTION_NAMESPACE);
		
	    cbrService = null;
		cbrOnButton.setEnabled(true);
		cbrOffButton.setEnabled(false);
	    
		printLineInMonitor("Cbr Resilience Service stopped");
   
		cbrResilienceStarted = false;
	}
	
	private void setConnectionParameters(String ip, String port) {
		this.connectParameters = new GEMOMParameters();
		connectParameters.put("ConnectionString", "client@"+ip+":"+port);
	}
	 
	/**
	 * Performs publish of data entered by user
	 */
	protected void onPublish() {
		
		String namespace = m_namespaceField.getText();
		String topic = m_topicField.getText();
		if (topic == null || topic.equalsIgnoreCase("")) {
			return;
		}
		if (VOLUMETRY_TEST_TOPIC.equalsIgnoreCase(topic)) {
			startVolumetryTest(topic);
		} else {
			GEMOMData data = new GEMOMData();
			for (int i = 0; i < 4; i++) {
				String fieldName = m_fieldNameFields[i].getText();
				if (fieldName.equalsIgnoreCase("")) {
					continue;
				}
				String fieldValue = m_fieldValueFields[i].getText();
				data.put(fieldName, fieldValue);
			}
			// getGEMOMBrokerInterface().publish(this, topic, data, null);
			getGEMOMBrokerInterface().publish(null, namespace, topic, data,
					null, null);
			printLineInMonitor(getTimeAsString() + ": Publishing on " + topic
					+ " , data:");
			printLineInMonitor(formatHashtable(data));
		}
	}
	
	/**
	 * Performs publish of data entered by user
	 */
	protected void publishSolution(String namespace, String topic, Hashtable<String, String> solution) {
		 
		GEMOMData data = new GEMOMData();
		 
		Enumeration en = solution.keys();
		
		int row=0;
		
		while(en.hasMoreElements())
		{
			String name = (String)en.nextElement();
			String value = solution.get(name).toString();
			
	        data.put(name, value);
			
			row++;
		}
		  
		// getGEMOMBrokerInterface().publish(this, topic, data, null);
		getGEMOMBrokerInterface().publish(null, namespace, topic, data,
				null, null);
		printLineInMonitor(getTimeAsString() + ": Publishing solution on " + topic
				+ " , data:");
		printLineInMonitor(formatHashtable(data)); 
	}
	
	/**
	 * Performs subscribe operation on topic entered by user
	 */
	
	protected void onSubscribe() {
		String namespace = m_namespaceSubscribeTopicField.getText();
		String topic = m_subscribeTopicField.getText();
		if (topic == null || topic.equalsIgnoreCase("")) {
			return;
		}
		GEMOMClientData clientData = new GEMOMClientData();
		clientData.put(topic + "_CLIENT_DATA_KEY", topic
				+ "_CLIENT_DATA_VALUE_" + (int) (Math.random() * 1000));
		getGEMOMBrokerInterface().subscribeOnTopic(this, namespace, topic,
				clientData, null);

		printLineInMonitor(getTimeAsString() + ": Subscribing on topic: "
				+ topic + " with clientData:");
		printLineInMonitor(formatHashtable(clientData));
		
		subscription.addTopic(namespace, topic);
		updateTree();
		 
	}
	
	protected void onSubscribe(String namespace, String topic) {
		//String namespace = namespaceField.getText();
		//String topic = topicField.getText();
		if (topic == null || topic.equalsIgnoreCase("")) {
			return;
		}
		GEMOMClientData clientData = new GEMOMClientData();
		clientData.put(topic + "_CLIENT_DATA_KEY", topic
				+ "_CLIENT_DATA_VALUE_" + (int) (Math.random() * 1000));
		getGEMOMBrokerInterface().subscribeOnTopic(this, namespace, topic,
				clientData, null);

		printLineInMonitor(getTimeAsString() + ": Subscribing on topic: "
				+ topic + " with clientData:");
		printLineInMonitor(formatHashtable(clientData));
		
		subscription.addTopic(namespace, topic);
		updateTree();
		 
	}
	
	/**
	 * Performs subscribe operation on topic entered by user
	 */
	protected void onUnSubscribe(String namespace, String topic) {
		//String namespace = m_namespaceSubscribeTopicField.getText();
		//String topic = m_subscribeTopicField.getText();
		if (topic == null || topic.equalsIgnoreCase("")) {
			return;
		}
		GEMOMClientData clientData = new GEMOMClientData();
		clientData.put(topic + "_CLIENT_DATA_KEY", topic
				+ "_CLIENT_DATA_VALUE_" + (int) (Math.random() * 1000));
		getGEMOMBrokerInterface().unsubscribeFromTopic(this, namespace, topic,
				clientData, null);

		printLineInMonitor(getTimeAsString() + ": Unsubscribing from topic: "
				+ topic + " with clientData:");
		printLineInMonitor(formatHashtable(clientData));
		
		subscription.removeTopic(namespace, topic);
		updateTree();
		 
	}

	protected void onRename() {
		getGEMOMBrokerInterface().renameTopic(this,
				m_namespaceRenameTopicField.getText(),
				m_renameTopicField.getText(), m_newTopicField.getText(), null,
				null);
	}

	private void onMoveTopic() {
		getGEMOMBrokerInterface().moveTopic(this,
				m_sourceNamespaceMoveTopicField.getText(),
				m_destinationNamespaceMoveTopicField.getText(),
				m_moveTopicField.getText(), null, null);
	}

	protected void onDelete() {
		getGEMOMBrokerInterface().deleteTopic(this,
				m_namespaceDeleteTopicField.getText(),
				m_deleteTopicField.getText(), null, null);
	}

	protected void onNamespaceRename() {
		getGEMOMBrokerInterface().renameNamespace(this,
				m_namespaceRenameField.getText(),
				m_namespaceNewField.getText(), null, null);
	}

	private void onNamespaceMove() {
		getGEMOMBrokerInterface().moveNamespace(this,
				m_namespaceMoveField.getText(),
				m_namespaceMoveDestinationField.getText(), null, null);
	}

	protected void onNamespaceDelete() {
		getGEMOMBrokerInterface().deleteNamespace(this,
				m_namespaceDeleteField.getText(), null, null);
	}
	
	public void initSubscription() {
		
		checkIfConnected();
		
		
	    //onSubscribe(scenarioFile.counter_namespace,client_ip+":"+client_port);
		if(subscription == null)
			this.subscription = new Subscription("CBR Resilience Subscription");
		
	    this.subscription.addNamespace(CbrUtil.CBR_QUERY_NAMESPACE);
	    this.subscription.addNamespace(CbrUtil.CBR_SOLUTION_NAMESPACE);
		
		if(subscription != null && subscription.getSize() > 0){
			Enumeration nss  = subscription.getAllNamespace().keys();
			while(nss.hasMoreElements()){
				String ns = nss.nextElement().toString();
				if (ns != null || !ns.equalsIgnoreCase("")) {
					
					GEMOMClientData clientData = new GEMOMClientData();
					clientData.put(ns + "_CLIENT_DATA_KEY", ns
							+ "_CLIENT_DATA_VALUE_" + (int) (Math.random() * 1000));
					getGEMOMBrokerInterface().subscribeOnNamespace(this, ns,
							clientData, null);
					
					printLineInMonitor(getTimeAsString() + ": Scribing on namespace: "
							+ ns + " with clientData:");
					printLineInMonitor(formatHashtable(clientData));
				}       
			}	
		}
		
		updateTree();
		
	}
	
	protected void onNamespaceSubscribe() {
		String namespace = m_namespaceSubscribeField.getText();
		debug("onNamespaceSubscribe " + namespace);
		if (namespace == null || namespace.equalsIgnoreCase("")) {
			return;
		}
		GEMOMClientData clientData = new GEMOMClientData();
		clientData.put(namespace + "_CLIENT_DATA_KEY", namespace
				+ "_CLIENT_DATA_VALUE_" + (int) (Math.random() * 1000));
		getGEMOMBrokerInterface().subscribeOnNamespace(this, namespace,
				clientData, null);
		
		subscription.addNamespace(namespace);
		updateTree(); 

		printLineInMonitor(getTimeAsString() + ": Subscribing on namespace: "
				+ namespace + " with clientData:");
		printLineInMonitor(formatHashtable(clientData));

		// TODO: delete later, this is just temporary until subscribeOnNamespace
		// in psproxy is finished
		// String FS = "\034";
		// ((GEMOMBrokerInterfaceImpl) getGEMOMBrokerInterface())
		// .onNamespaceUpdate("__DIR" + FS + namespace + FS + "/n1/n2/t1"
		// + FS + "/n3/n4/t2");
	}

	protected void onNamespaceSubscribe(String namespace) {
		//String namespace = m_namespaceSubscribeField.getText();
		//debug("onNamespaceSubscribe " + namespace);
		if (namespace == null || namespace.equalsIgnoreCase("")) {
			return;
		}
		GEMOMClientData clientData = new GEMOMClientData();
		clientData.put(namespace + "_CLIENT_DATA_KEY", namespace
				+ "_CLIENT_DATA_VALUE_" + (int) (Math.random() * 1000));
		getGEMOMBrokerInterface().subscribeOnNamespace(this, namespace,
				clientData, null);
		
		printLineInMonitor(getTimeAsString() + ": Subscribing on namespace: "
				+ namespace + " with clientData:");
		printLineInMonitor(formatHashtable(clientData));
		
		subscription.addNamespace(namespace);
		updateTree(); 

		// TODO: delete later, this is just temporary until subscribeOnNamespace
		// in psproxy is finished
		// String FS = "\034";
		// ((GEMOMBrokerInterfaceImpl) getGEMOMBrokerInterface())
		// .onNamespaceUpdate("__DIR" + FS + namespace + FS + "/n1/n2/t1"
		// + FS + "/n3/n4/t2");
	}
	

	protected void onNamespaceUnSubscribe(String namespace) {
	 
		if (namespace == null || namespace.equalsIgnoreCase("")) {
			return;
		}
		
		GEMOMClientData clientData = new GEMOMClientData();
		clientData.put(namespace + "_CLIENT_DATA_KEY", namespace
				+ "_CLIENT_DATA_VALUE_" + (int) (Math.random() * 1000));
	  
		// the namespace has to be embraced by slashes
		getGEMOMBrokerInterface().unsubscribeFromNamespace(this, Util.addSlash(namespace),
				clientData, null);
		 
		printLineInMonitor(getTimeAsString() + ": Unsubscribing from namespace: "
				+ namespace + " with clientData:");
		printLineInMonitor(formatHashtable(clientData));
		 
		subscription.removeNamespace(namespace);
		
		updateTree();
		 
		
		// TODO: delete later, this is just temporary until subscribeOnNamespace
		// in psproxy is finished
		// String FS = "\034";
		// ((GEMOMBrokerInterfaceImpl) getGEMOMBrokerInterface())
		// .onNamespaceUpdate("__DIR" + FS + namespace + FS + "/n1/n2/t1"
		// + FS + "/n3/n4/t2");

	}

	public boolean update(String namespace, String topic,
			GEMOMMessageType messageType, GEMOMData data,
			GEMOMClientData clientData) {

	
		namespace = Util.stripSlash(namespace);
		
		listenToQuery(namespace, topic, data);
		
		if(!m_publishToSystemOut){
		
		    // Print all updates on topics
	        //  printLineInAllSubMonitor(getTimeAsString() + ": Update on topic@Namespace = " + 
		    //topic+"@/"+namespace+ " messageType: " + messageType + " with data:");
		    //printLineInAllSubMonitor(formatHashtable(data));
		    //printLineInAllSubMonitor("and client data:");
		    //printLineInAllSubMonitor(formatHashtable(clientData)+"\n");
		    
			
			// update the data in the Table all sub
			
			// setup the table for the 
			//DefaultTableModel model= new DefaultTableModel(colName,0);
			DefaultTableModel model1=(DefaultTableModel) AllSubTable.getModel();
			
			Enumeration en = data.keys();
			
			int row=0;
			
			while(en.hasMoreElements() && row < tableRowCount)
			{
				String fieldName = (String)en.nextElement();
				String fieldValue=data.get(fieldName).toString();
				
				Object[] rowData= new Object[4];

				rowData[0]=namespace;
				rowData[1]=topic;				
				rowData[2]= fieldName;
				rowData[3]= fieldValue;
				
				
				model1.setValueAt(rowData[0],row, 0);
				model1.setValueAt(rowData[1],row, 1);
				model1.setValueAt(rowData[2],row, 2);
				model1.setValueAt(rowData[3],row, 3);
				
				row++;
			}
			
			// empty the rest of the table
			while(row < tableRowCount){
				model1.setValueAt("",row, 0);
				model1.setValueAt("",row, 1);
				model1.setValueAt("",row, 2);
				model1.setValueAt("",row, 3);
				
				row++;
			}
			
			//AllSubTable.setModel(model);
		  
			
		    // See what's there in sub monitors by selecting namespace/topic.
		    if (shouldPrintUpdateInMonitor(topic) && isUserSelectedUpdate(namespace, topic, updateCode)) {
			    
		    	// update the data in the Table sub
				DefaultTableModel model2= (DefaultTableModel) SubTable.getModel();
				
				Enumeration enT = data.keys();
				
				int rowT=0;
				
				while(enT.hasMoreElements() && rowT < tableRowCount)
				{
					String fieldName = (String)enT.nextElement();
					String fieldValue=data.get(fieldName).toString();
					
					Object[] rowData= new Object[4];

					rowData[0]=namespace;
					rowData[1]=topic;				
					rowData[2]= fieldName;
					rowData[3]= fieldValue;
					
					model2.setValueAt(rowData[0],rowT, 0);
					model2.setValueAt(rowData[1],rowT, 1);
					model2.setValueAt(rowData[2],rowT, 2);
					model2.setValueAt(rowData[3],rowT, 3);
					
					rowT++;
					
					//model2.addRow(rowData);
				}
				
				// empty the rest of the table
				while(rowT < tableRowCount){
					model2.setValueAt("",rowT, 0);
					model2.setValueAt("",rowT, 1);
					model2.setValueAt("",rowT, 2);
					model2.setValueAt("",rowT, 3);
					
					rowT++;
				}
				
				//SubTable.setModel(model2);
		    	

			    //printLineInSubMonitor(getTimeAsString() + ": Update on topic@Namespace = " + 
				//	    topic+"@/"+namespace+ " messageType: " + messageType + " with data:");
			    //printLineInSubMonitor(formatHashtable(data)+"\n");
			    //printLineInSubMonitor("and client data:");
			    //printLineInSubMonitor(formatHashtable(clientData));
			    
		    }
	 
		}
		else{
			System.out.println(namespace);
			System.out.println(topic);
			printGEMOMData(data);
		}

		m_updateCounter++;
		// if ((m_updateCounter % m_volumetryTestPublishCount) == 0
		// || (m_updateCounter % 1000) == 0) {
		// printLineInMonitor(getTimeAsString() + ": Update no. "
		// + m_updateCounter + " on topic " + topic + " with data");
		// printLineInMonitor(formatHashtable(data));
		// printLineInMonitor("and client data:");
		// printLineInMonitor(formatHashtable(clientData));
		// } 
        
		return true;  
	}
	  
	private void listenToQuery(String namespace, String topic, GEMOMData data){
		if(namespace.equalsIgnoreCase(CbrUtil.CBR_QUERY_NAMESPACE)){
		
			// Automatic service mode
			if(shouldAutoRespond ){
				if(cbrService.updateState(data)){
					
					// publish the actual solution to the solution namespace
					// the topic name is the topic name of the original query,
					// which could be a reference number that is useful and handy
					this.publishSolution(CbrUtil.CBR_SOLUTION_NAMESPACE, topic,
							cbrService.getSol(CbrOnUpdate.solkey));
					
					JOptionPane.showMessageDialog(this, "A query for Broker Re-Allocation has been" +
							" processed and solution published to "+ topic+"@/"+
							CbrUtil.CBR_SOLUTION_NAMESPACE, "Broker Allocation Query Served",
							JOptionPane.INFORMATION_MESSAGE);
				}
				else{
					JOptionPane.showMessageDialog(this, "Incorrect query message received and will not be served", "Wrong message format",
							JOptionPane.ERROR_MESSAGE);
					
				}
			
			}
			// Manual mode
			else{ 
				// check if query data is valid, and if valid pull up solutions
				if(cbrService.updateState(data)){
					// publish the actual solution to the solution namespace
					// the topic name is the topic name of the original query,
					// which could be a reference number that is useful and handy
					
					boolean shouldProcess = JOptionPane
					.showConfirmDialog(
							this,
							"A valid query has been received, generate a solution and send it to " +
							" OverlayManger?",
							"Query received", JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION;
			
			
					if(shouldProcess){
						this.publishSolution(CbrUtil.CBR_SOLUTION_NAMESPACE, topic,
								cbrService.getSol(CbrOnUpdate.solkey)); 
						
						JOptionPane.showMessageDialog(this, "A query for Broker Re-Allocation has been" +
								" processed and solution published to "+ topic+"@/"+
								CbrUtil.CBR_SOLUTION_NAMESPACE, "Broker Allocation Query Served",
								JOptionPane.INFORMATION_MESSAGE);
					}
					 
				} 
 
			}// end of Manual mode
			 
		} // end of Query namespace check
		
	}

	private boolean shouldPrintUpdateInMonitor(String topic) {
		return !VOLUMETRY_TEST_TOPIC.equals(topic)
				|| (VOLUMETRY_TEST_TOPIC.equals(topic) && m_showVolumetryMonitorMessages);
	}

	void printInMonitor(String msg) {
		m_monitorMainArea.append(msg);
	}

	void printLineInMonitor(String msg) {
		printInMonitor(msg);
		m_monitorMainArea.append("\n");
	}

	protected void startVolumetryTest(final String topic) {
		final GEMOMData data = new GEMOMData();
		for (int i = 0; i < 4; i++) {
			String fieldName = m_fieldNameFields[i].getText();
			if (fieldName.equalsIgnoreCase("")) {
				continue;
			}
			String fieldValue = m_fieldValueFields[i].getText();
			data.put(fieldName, fieldValue);
		}

		new Thread() {

			public void run() {

				long publishTime = 0;
				Date generalStart = new Date();
				printLineInMonitor(getTimeAsString()
						+ ": Starting volumetry test for "
						+ m_volumetryTestPublishCount + " iterations on topic "
						+ topic);

				for (int i = 0; i < m_volumetryTestPublishCount; i++) {
					// add random data so PSProxy.dll wouldn't filter data as it
					// was already
					// successfully published
					data.put("RandomData", "" + i);
					data
							.put(
									"FillerData",
									"1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890");

					// getGEMOMBrokerInterface().publish(GEMOMTestApp2.this,
					// topic, data, null);
					getGEMOMBrokerInterface().publish(null, "", topic, data,
							null, null);

					if (m_showVolumetryMonitorMessages)
						printLineInMonitor(getTimeAsString() + ": Publishing "
								+ data + " on " + topic);
				}
				printLineInMonitor(getTimeAsString()
						+ ": Total publish time in ms: " + publishTime
						+ " for " + m_volumetryTestPublishCount + " publishes.");
				printLineInMonitor(getTimeAsString()
						+ ": Average publish time in ms (per publish: "
						+ ((double) publishTime) / m_volumetryTestPublishCount);
				Date generalEnd = new Date();
				printLineInMonitor(getTimeAsString()
						+ ": Total time (publish and overhead) in ms: "
						+ (generalEnd.getTime() - generalStart.getTime())
						+ " for " + m_volumetryTestPublishCount + " publishes.");

			}
		}.start();
	}

	protected String getTimeAsString() {
		return m_sdf.format(new Date());
	}

	@Override
	public boolean updateNamespace(String namespace, String topic,
			String newName, GEMOMMessageType messageType,
			GEMOMClientData clientData) {

		namespace = Util.stripSlash(namespace);
		
		if (messageType.equals(GEMOMMessageType.TOPIC_CREATE)) {
			printLineInMonitor(getTimeAsString() + ":topic " + topic + " created, subscribing to: " + namespace
					+ topic);
			getGEMOMBrokerInterface().subscribeOnTopic(this, namespace, topic,
					clientData, null);
			
			subscription.addTopic(namespace, topic);
			updateTree();
			 
		}
		// uncomment below block if you want to unsubscribe when topic is
		// deleted from
		// a namespace

		// else if (messageType.equals(GEMOMMessageType.TOPIC_DELETE)) {
		// debug("topic " + topic + " deleted, unsubscribing from: "
		// + namespace + topic);
		// getGEMOMBrokerInterface().unsubscribeFromTopic(this, namespace,
		// topic, clientData, null);
		// }
		return true;
	}

	private void updateTree(){
		
		DefaultMutableTreeNode top = subscription.buildTreeNode();

		DefaultTreeModel tmodel=new DefaultTreeModel(top);

		tree.setModel(tmodel);

		expandAll(tree,new TreePath(top),true);
		
	}
	
	@Override
	public String getGEMOMClientName() {
		return this.getClass().getName();
	}

	public GEMOMBrokerAdapter getGEMOMBrokerInterface() {
		if (m_broker == null) {
			m_broker = new GEMOMBrokerAdapterImpl();
			// no debug info as it gets console difficult to follow
			((GEMOMBrokerAdapterImpl) m_broker).setShouldPrintDebugInfo(false);
			//GEMOMParameters connectParameters = new GEMOMParameters();
			//boolean connected = m_broker.connect(getGEMOMClientName(), this,
			//		connectParameters, null, null);
			//if (!connected) {
			//	debug("ERROR: Couldn't connect to GEMOM broker");
			//}
		}
		return m_broker;
	}

	private void debug(String string) {
		System.out.println("GEMOMSysClientsListenerDemo "
				+ m_sdf.format(new Date()) + ": " + string);
	}
	
	protected void debug(Object o) {
		System.out.println(o);
	}


	protected void onOptionSubscribe(){
		String namespace = namespaceField.getText();
		String topic = topicField.getText();
		if (!namespace.equalsIgnoreCase("")){ 
			
			if (topic == null || topic.equalsIgnoreCase("")) {
				onNamespaceSubscribe(namespace);
				printLineInMonitor(getTimeAsString() + ": Manually subscribing on namespace: " + namespace);
				//subscription.addNamespace(namespace);
				
				
			}
			else{
				onSubscribe(namespace, topic);
				printLineInMonitor(getTimeAsString() + ": Manually subscribing on topic@/namespace: " + topic + "@/" + namespace);
				//subscription.addTopic(namespace, topic);
			} 
		}
	}

	protected void onOptionUnsubscribe(){
		
		 DefaultMutableTreeNode node = (DefaultMutableTreeNode)tree.getLastSelectedPathComponent();

		    String rootName = tree.getModel().getRoot().toString();
		    
         if (node == null){
             return;
         }

         Object nodeInfo = node.getUserObject();
         // topic selected
         
         if(!node.isRoot()){
             if (node.isLeaf()){
         	    // topic is selected
         	    if (!node.getParent().toString().equalsIgnoreCase(rootName)){
                     String topicName = (String)nodeInfo;
                     String nsName = node.getParent().toString();
                     onUnSubscribe(nsName, topicName);
                    // subscription.removeTopic(nsName, topicName);
         	    }
         	     //A particular namespace selected, and it has no children topics subscribed
         	    else{
             	    String nsName = (String)nodeInfo;
                 	onNamespaceUnSubscribe(nsName);
                 	//subscription.removeNamespace(nsName);
         	    }
         	    return;
             }
             // a namespace is selected, and it has children topics which it needs to un-subscribe too
             else{
          	    String nsName = (String)nodeInfo;
          	    // get all topics in this namespace
          	    for(int i = 0; i < node.getChildCount(); i++){
          	    	TreeNode tempNode = node.getChildAt(i);
          	    	String tempTopic = tempNode.toString();
          	    	if(tempTopic != null)
          	    		onUnSubscribe(nsName, tempTopic);
          	    }
             	onNamespaceUnSubscribe(nsName);
             	// Remove one ns removes all topics below it
             	subscription.removeNamespace(nsName);
             
             }
         }
         //All namespace selected
         else{
         }
        
         updateTree();
	}

	
	private void expandAll(JTree tree, TreePath parent, boolean expand) {
		// Traverse children
		DefaultMutableTreeNode node = (DefaultMutableTreeNode)parent.getLastPathComponent();
		if (node.getChildCount() >= 0) {
			for (Enumeration e=node.children(); e.hasMoreElements(); ) {
				DefaultMutableTreeNode n = (DefaultMutableTreeNode)e.nextElement();
				TreePath path = parent.pathByAddingChild(n);
				expandAll(tree, path, expand);
			}
		}

		// Expansion or collapse must be done bottom-up
		if (expand) {
			tree.expandPath(parent);
		} else {
			tree.collapsePath(parent);
		}
	}
	
	protected void setUpdateSetting(boolean allNameSpace, String nsName, String topicName){
	    if(allNameSpace){
	    	updateCode = 0;
	    	updateStrings[0] = "";
	    	updateStrings[1] = "";
	    }
	    else if (nsName != null && !nsName.equalsIgnoreCase("")){
	    	if (topicName == null && topicName.equalsIgnoreCase("")){
	    	    updateCode = 1;
	    	    updateStrings[0] = nsName;
	    	    updateStrings[1] = topicName;
	    	}
	    	else{
	    		updateCode = 2;
	    	    updateStrings[0] = nsName;
	    	    updateStrings[1] = topicName;
	    	}
	    }
	}
	
	private boolean isUserSelectedUpdate(String namespace, String topic, int code){
		//printLineInSubMonitor("NS = "+namespace+" and topic = "+topic +" and code = "+code);
	    if(updateCode == 1 && updateStrings[0].equalsIgnoreCase(namespace)){
	    	return true;
	    }
	    if(updateCode == 2 && updateStrings[0].equalsIgnoreCase(namespace) && updateStrings[1].equalsIgnoreCase(topic)){
	        return true;
	    }
	    else
	    	return false;
	    
	}

	public static String formatHashtable(Hashtable ht) {
		return formatMap(ht, 0);
	}

	public static String formatMap(Map map) {
		return formatMap(map, 0);
	}

	public static String formatMap(Map map, int level) {
		StringBuffer sb = new StringBuffer();

		if (map != null) {
			Object[] keysArray = new Object[map.size()];

			Set keys = map.keySet();

			int i = 0;
			Iterator it = keys.iterator();
			while (it.hasNext()) {
				keysArray[i] = it.next();
				i++;
			}
			String leading = "";
			for (i = 0; i < level; i++) {
				leading += "\t";
			}
			if (keysArray != null && keysArray.length > 0
					&& keysArray[0] instanceof Comparable) {
				Arrays.sort(keysArray);
			}

			for (i = 0; i < keysArray.length; i++) {
				if (map.get(keysArray[i]) instanceof Map) {
					sb.append(leading + keysArray[i] + " =\n"
							+ formatMap((Map) map.get(keysArray[i]), level + 1)
							+ "\n");

				} else {
					sb.append(leading + keysArray[i] + " = "
							+ map.get(keysArray[i]) + "\n");
				}
			}
		} else {
			sb.append("null");
		}

		return sb.toString();
	}
	
	private static void printGEMOMData(Map map) {
	
		if (map != null) {
			Object[] keysArray = new Object[map.size()];

			Set keys = map.keySet();

			int i = 0;
			Iterator it = keys.iterator();
			while (it.hasNext()) {
				keysArray[i] = it.next();
				i++;
			}
			if (keysArray != null && keysArray.length > 0
					&& keysArray[0] instanceof Comparable) {
				Arrays.sort(keysArray);
			}

			for (i = 0; i < keysArray.length; i++) {
				System.out.println(keysArray[i]);
				System.out.println(map.get(keysArray[i]));
			}
		} else {
		}

	}
}

